﻿#include "MetricsCompute.h"
#include "ta_libc.h"


MetricsCompute::MetricsCompute()
{
	TA_RetCode retcode;
	retcode = TA_Initialize();

}


MetricsCompute::~MetricsCompute()
{
	TA_RetCode retcode;
	retcode = TA_Shutdown();
}

void MetricsCompute::MA(ConstFVecPtr pCloseValues, int inTimePeriod, MetData::MAMetrice &outMa)
{
	TA_Real *outValue = new TA_Real[pCloseValues.size()];
	TA_Integer out_begin = 0;
	TA_Integer out_nb_element = 0;
	TA_RetCode retCode = TA_S_MA(0, pCloseValues.size() - 1, pCloseValues.data(), inTimePeriod, TA_MAType_SMA, &out_begin, &out_nb_element, outValue);

	outMa.StartIndex = out_begin;
	for (int i = 0; i < out_nb_element; ++i)
	{
		outMa.Line.emplace_back((float)outValue[i]);
	}

	delete[]outValue;
}

void MetricsCompute::MACD(ConstFVecPtr pCloseValues, int optInFastPeriod, int optInSlowPeriod, int optInSignalPeriod, MetData::MACDMeterice &outVal)
{
	TA_Real *outMACDValue = new TA_Real[pCloseValues.size()];
	TA_Real *outMACDSignalValue = new TA_Real[pCloseValues.size()];
	TA_Real *outMACDHistValue = new TA_Real[pCloseValues.size()];
	/*
	12日EMA的计算：EMA12 = 前一日EMA12 X 11/13 + 今日收盘 X 2/13
	26日EMA的计算：EMA26 = 前一日EMA26 X 25/27 + 今日收盘 X 2/27
	差离值（DIF）的计算： DIF = EMA12 - EMA26，即为talib-MACD返回值macd
	根据差离值计算其9日的EMA，即离差平均值，是所求的DEA值。今日DEA = （前一日DEA X 8/10 + 今日DIF X 2/10），即为talib-MACD返回值signal
	DIF与它自己的移动平均之间差距的大小一般BAR=（DIF-DEA)2，即为MACD柱状图。但是talib中MACD的计算是bar = (dif-dea)1
	*/
	TA_Integer out_begin = 0;
	TA_Integer out_nb_element = 0;
	TA_RetCode retCode = TA_S_MACD(0, pCloseValues.size() - 1, pCloseValues.data(), optInFastPeriod, optInSlowPeriod, optInSignalPeriod, &out_begin, &out_nb_element, outMACDValue, outMACDSignalValue, outMACDHistValue);
	outVal.StartIndex = out_begin;
	for (int i = 0; i < out_nb_element; ++i)
	{
		outVal.MACDPara.emplace_back((float)outMACDValue[i]);
		outVal.MACDSignal.emplace_back((float)outMACDSignalValue[i]);
		outVal.MACDHist.emplace_back((float)outMACDHistValue[i]);
	}

	delete[]outMACDValue;
	delete[]outMACDSignalValue;
	delete[]outMACDHistValue;
}

void MetricsCompute::ATR(ConstFVecPtr pHighValues, ConstFVecPtr pLowValues, ConstFVecPtr pCloseValues, int optInTimePeriod, MetData::ATRMetrice & outVal)
{
	TA_Real *outValue = new TA_Real[pCloseValues.size()];

	TA_Integer out_begin = 0;
	TA_Integer out_nb_element = 0;
	TA_RetCode retCode = TA_S_ATR(0, pCloseValues.size() - 1, pHighValues.data(), pLowValues.data(), pCloseValues.data(), optInTimePeriod, &out_begin, &out_nb_element, outValue);
	outVal.StartIndex = out_begin;
	for (int i = 0; i < out_nb_element; ++i)
	{
		outVal.Values.emplace_back((float)outValue[i]);
	}
	delete[]outValue;
}

void MetricsCompute::Boll(ConstFVecPtr pCloseValues, int optInTimePeriod, MetData::BollMetrice &outVal)
{
	//outRealUpperBand.resize(pCloseValues.size());
	//outRealMiddleBand.resize(pCloseValues.size());
	//outRealLowerBand.resize(pCloseValues.size());

	TA_Real *pRealUpperBand = new TA_Real[pCloseValues.size()];
	TA_Real *pRealMiddleBand = new TA_Real[pCloseValues.size()];
	TA_Real *pRealLowerBand = new TA_Real[pCloseValues.size()];

	TA_Integer out_begin = 0;
	TA_Integer out_nb_element = 0;
	/*
	int optInTimePeriod,    // MA区间（MA5、MA10、MA20...）
	double optInNbDevUp,  // 上轨线标准差（默认为2）
	double optInNbDevDn,  // 下轨线标准差（默认为2）
	MAType optInMAType,   // MA线的类型:MAType.Sma
	MInteger outBegIdx,   // 输出数据开始下标
	MInteger outNBElement,    // 输出数据个数
	double outRealUpperBand[],  // 上轨线UP数据
	double outRealMiddleBand[], // 中轨线MB数据
	double outRealLowerBand[] ) // 下轨线DN数据
	*/
	TA_RetCode retCode = TA_S_BBANDS(0, pCloseValues.size() - 1, pCloseValues.data(), optInTimePeriod, 2, 2, TA_MAType_SMA, &out_begin, &out_nb_element, pRealUpperBand, pRealMiddleBand, pRealLowerBand);
	outVal.StartIndex = out_begin;
	
	for (int i = 0; i < out_nb_element; ++i)
	{
		outVal.UpperBand.emplace_back((float)pRealUpperBand[i]);
		outVal.MiddleBand.emplace_back((float)pRealMiddleBand[i]);
		outVal.LowerBand.emplace_back((float)pRealLowerBand[i]);
	}

	delete[]pRealUpperBand;
	delete[]pRealMiddleBand;
	delete[]pRealLowerBand;
}

void MetricsCompute::OVB(ConstFVecPtr pCloseValues, ConstFVecPtr pVolumeValues, MetData::OVBMetrice &outVal)
{
	TA_Real *pValues = new TA_Real[pCloseValues.size()];
	TA_Integer out_begin = 0;
	TA_Integer out_nb_element = 0;
	TA_RetCode retCode = TA_S_OBV(0, pCloseValues.size() - 1, pCloseValues.data(), pVolumeValues.data(), &out_begin, &out_nb_element, pValues);
	outVal.StartIndex = out_begin;
	for (int i = 0; i < out_nb_element; ++i)
	{
		outVal.Values.emplace_back((float)pValues[i]);
	}

	delete[]pValues;
}
